/*

    Licensed under the Apache License, Version 2.0 (the "License"); 
    you may not use this file except in compliance with the License. 
    You may obtain a copy of the License at 
    http://www.apache.org/licenses/LICENSE-2.0 
    Unless required by applicable law or agreed to in writing, software 
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    See the License for the specific language governing permissions and 
    limitations under the License.
      
 */

package jforex.api;

import java.awt.Image;
import java.util.Currency;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import javax.swing.Icon;

import com.dukascopy.api.IBar;
import com.dukascopy.api.IOrder;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.Period;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.IOrder.State;

/**
 * 
 * This interface represents an set of functions helping to program in JForex API.<br>
 *  Here is example how interface should be instantiated, usually in <a target="_top" href="http://www.dukascopy.com/swiss/docs/api/com/dukascopy/api/IStrategy.html#onStart(com.dukascopy.api.IContext)">onStart()</a> function of <a a target="_top" href="http://www.dukascopy.com/swiss/docs/api/com/dukascopy/api/IStrategy.html">IStrategy</a><br>
 * <code> IBox box = new JFToolBox(context);</code>.  
 * 
 * 
 */
public interface IBox {

    /**
     * Rounding function
     * 
     * @param value
     * @param precision
     * @return - rounded value
     */
    double round(double value, int precision);

    /**
     * Round to half pip.
     * Useful since server side didn't pass prices other then rounded to half a pip.
     * 
     * @param price
     * @return
     */
    double roundHalfPip(double price);

    //=================================================
    // EASY ORDER USAGE
    //=================================================

    /**
     * Create an order and return result synchronously.
     * 
     * @param instrument 
     * @param cmd
     * @param lot
     * @param price 
     * @param slippage
     * @param stopLoss (in pips!)
     * @param takeProfit (in pips!)
     * @param magic
     * @return IOrder as result
     * @throws JFException 
     */

    IOrder submitOrderSync(Instrument instrument, OrderCommand cmd, double lot, double priceLevel, double slippage, int stopLoss, int takeProfit, int magic) throws JFException;

    /**
     * Close order sync.
     * @param order
     * @return
     * @throws JFException
     */
    IOrder closeOrderSync(IOrder order) throws JFException;
    
    void closeAllSync(List<IOrder> orders) throws JFException;
    
    /**
     * This helper function return orders with specified instrument and state
     * 
     * @param instrument
     *            - needed instrument. If null : all instruments will be
     *            returned
     * @param state
     *            - needed state. If null all states will be returned * 
     * @param magic 
     *            - order magic number. If 0 or less then 0 - magic
     *            numbers will not will not be checked
     *       
     * @param state isLong
     *            - if not null, filter for position side (true for long positions , false for short)
     * 
     * @return - list of orders, return empty list if not found
     * @throws JFException
     */
    
    
    
    public List<IOrder> getOrders(Instrument instrument, IOrder.State state, Boolean isLong, int magic) throws JFException;
    
    public List<IOrder> getOrders(Instrument instrument, IOrder.State state, int magic) throws JFException;
    
   
    
    public List<IOrder> getOrders(Instrument instrument, State filled) throws JFException;
    
    /**
     * Merge all orders synchronously. Removes automatically any SL or TP before merging.
     */
    IOrder mergeOrdersSync(String label, List<IOrder> positions) throws JFException;
    /**
     * Merge all orders synchronously, but can merge from collection with different instruments 
     * 
     */
    public List<IOrder> mergeAllInstrumentsOrdersSync(int magic, List<IOrder> positions) throws JFException;

    String generateLabel(int magic);

    int getMagicNumber(IOrder order);

    //=================================================
    // RESOURCES
    //=================================================

    /**
     * 
     * @param path to image
     * @return
     */
    public Image loadImage(String path);

    byte[] loadResource(String path);

    boolean playSound(String soundName);

    Icon loadIcon(String path);

    void print(Object... str);

    //=================================================
    // HISTORICAL ACCESS
    //=================================================

    List<IBar> getLastBars(Instrument instrument, Period period, OfferSide offerSide, int bars, boolean takeUnformedBar) throws JFException;

    IBar[] getNBars(Instrument instrument, Period period, OfferSide offerSide, int start, int count) throws JFException;

    //=================================================
    // USEFUL CALCULATIONS
    //=================================================

    /**
     * Calculates price level for stop loss if given:
     * 1.position/entry open price 
     * 2.stop loss in pips
     * 
     * @param instrument
     * @param cmd
     * @param openPrice
     * @param stopLossPips
     * @return
     */
    double calculateStopLoss(Instrument instrument, OrderCommand cmd, double openPrice, int stopLossPips) throws JFException;

    /**
     * Calculates price level for take profit if given:
     * 1.position/entry open price 
     * 2.take profit in pips
     * 
     * @param instrument
     * @param cmd
     * @param openPrice
     * @param takeProfitPips
     * @return
     * @throws JFException
     */
    double calculateTakeProfit(Instrument instrument, OrderCommand cmd, double openPrice, int takeProfitPips) throws JFException;

    /**
     * Converts money from one currency to another
     * 
     * @param amount
     * @param sourceCurrency
     * @param targetCurrency
     * @return
     * @throws JFException
     */
    double convertMoney(double amount, Currency sourceCurrency, Currency targetCurrency) throws JFException;

    /**
     * Calculates profit in absolute amount for given position 
     * 
     * @param order
     * @return
     * @throws JFException
     */
    double calculateProfitMoney(IOrder order) throws JFException;

    /**
     *  Calculates profit in absolute amount for given parameters
     * @param openPrice
     * @param closePrice
     * @param isLong
     * @param amountInMil
     * @return
     */

    public double calculateProfitMoney(double openPrice, double closePrice, boolean isLong, double amountInMil);

    /**
     * Calculates profit in pips for given parameters
     * 
     * @param order
     * @return
     * @throws JFException
     */

    public double calculateProfitPips(IOrder order) throws JFException;

    /**
     * Calculates profit in pips for given parameters
     * 
     * @param openPrice
     * @param closePrice
     * @param isLong
     * @param pipValue
     * @return
     */
    public double calculateProfitPips(double openPrice, double closePrice, boolean isLong, double pipValue);

    /**
     * Calculates weighted price for given positions
     * 
     * @param order
     * @return
     * @throws JFException
     */

    double weightedPrice(List<IOrder> orders) throws JFException;

    /**
     * calculate current exposure for given instrument for all orders
     * 
     * @param instrument
     * @param orders
     * @return
     * @throws JFException 
     */

    double getExposureByInstrument(Instrument instrument) throws JFException;
    
    /**
     * calculate current exposure for given instrument and given set of orders
     * 
     * @param instrument
     * @param orders
     * @return
     */
    
    double getExposureByInstrument(Instrument instrument, List<IOrder> orders);

    /**
     * Calculates exposure for given currency
     * @param currency
     * @return
     * @throws JFException 
     */

    double getExposureByCurrency(Currency currency) throws JFException;
    
    /**
     * Calculates exposure for given currency and specified set of orders
     * @param currency
     * @param orders
     * @return
     */
    public double getExposureByCurrency(Currency currency,List<IOrder> orders);

    /**
     * Calculates all exposure
     * @return
     * @throws JFException
     */

    Map<Currency, Double> getExposureByCurrency() throws JFException;

    //=================================================
    // UTILS
    //=================================================

    /**
     * Function pause for specified period in milliseconds
     * 
     * @param milliseconds
     */
    void sleep(int milliseconds);

    boolean evaluation(boolean onlyDemo, String string);

    Scanner getScanner(String string);

    /**
     * ISettings settings = box.getSettings("anyname");
     * you will get settings object , which represents property file in "files" directory
     * you can use get,put,remove methods in this object
     * This settings created especially for using by many strategies , 
     * so there will not be conflict if the same settings shared between strategies
     * 
     * @param string
     * @return
     */

    ISettings getSettings(String string);

    String multiargToString(String string, Object[] str);

    /**
    * Check time range 
    * 
    * @param timeRanges time ranges in format "8:30-12:40" all times in GMT
    * @param nowTime
    * @return - true if in given range, false if not
    * @throws JFException 
    */
    boolean isInTimeRange(long nowTime, String timeRange) throws JFException;
    
    boolean isBeforeTime(long nowTime, String timeCompareTo) throws JFException;
    


}
